
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fstream>
#include <string>
#include <iostream>
#include <string.h>
#include <sstream>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <io.h>

#define PI 3.141592

using namespace std;

#include "imageBMP.h"
#include "Grille.h"
#include "Game.h"


static int fileSize(char *filename) {
  struct _finddata_t c_file;
  intptr_t hFile;
  if( (hFile = _findfirst(filename,&c_file)) == -1L )
    return(-1);
  int size = c_file.size;
  _findclose(hFile);
  return(size);
}

static unsigned char *loadRawImage(char *filename) {
  int size = fileSize(filename);
  if ( size == -1 )
    return(NULL);
  unsigned char *img =(unsigned char *) malloc(size);
  if ( !img )
    return(NULL);
  FILE *f = fopen(filename,"rb");
  if ( !f ) {
    free(img);
    return(NULL); }
  fread(img,1,size,f);
  fclose(f);
  return(img);
} 

void glutPrint(float x, float y, LPVOID font, char* text, float r, float g, float b, float a) 
{ 
    if(!text || !strlen(text)) return; 
    bool blending = false; 
    if(glIsEnabled(GL_BLEND)) blending = true; 
    glEnable(GL_BLEND); 
    glColor4f(r,g,b,a); 
    glRasterPos2f(x,y); 
    while (*text) { 
        glutBitmapCharacter(font, *text); 
        text++; 
    } 
    if(!blending) glDisable(GL_BLEND); 
}  

int round(float arg){
	if(arg - floor(arg) > 0.5)
		return ceil(arg);
	else
		return floor(arg);
}

static const float blanc[] = { 1.0F,1.0F,1.0F,1.0F };
static const float jaune[] = { 1.0F,1.0F,0.0F,1.0F };
static const float rouge[] = { 1.0F,0.0F,0.0F,1.0F };
static const float vert[] = { 0.0F,1.0F,0.0F,1.0F };
static const float bleu[] = { 0.0F,0.0F,1.0F,1.0F };
static const float noir[] = { 0.0F,0.0F,0.0F,1.0F };

//static Game game("pacman.bmp",10);
static Game game("pacman19x19(2).bmp",5);
//static Game game("pacman48x48.bmp",5);
//Game game("../../svn/pacman19x19.bmp",5);

static int compteur=0;

int vueDessus;
int vueInterne;
int vueOrtho;

static int anim = 1;

static int rotateCamera = 0;

static void cercle(){
	float x,y;
	float radius = 0.5f;
	glBegin(GL_POLYGON);
		glColor3f(1.0f,1.0f,1.0f);
     
		x = (float)radius * cos(359 * PI/180.0f);
		y = (float)radius * sin(359 * PI/180.0f);
		for(int j = 0; j < 360; j++)
		{
			glVertex2f(x,y);
			x = (float)radius * cos(j * PI/180.0f);
			y = (float)radius * sin(j * PI/180.0f);
			glVertex2f(x,y);
		}
	glEnd();
}
static void cylindre(double h,double r,int n,int m) {
  glPushMatrix();
  glTranslatef(0.0F,0.0F,h/2);
  //glNormal3f(0.0F,0.0F,1.0F);
  //cercle();
  glTranslatef(0.0F,0.0F,-h);
  GLUquadricObj *qobj = gluNewQuadric();
  gluQuadricDrawStyle(qobj,GLU_FILL);
  gluCylinder(qobj,r,r,h,n,m);
  gluDeleteQuadric(qobj);
  //glNormal3f(0.0F,0.0F,-1.0F);
  //cercle();
  glPopMatrix();
}

static void mySolidCylindre(double hauteur,double rayon,int ns,int nl,int bases) {
  glEnable(GL_NORMALIZE);
  float normale[4];
  glGetFloatv(GL_CURRENT_NORMAL,normale);
  glPushMatrix();
  /*for ( int j = 0 ; j < nl ; j++ ) {
    float hi = hauteur/2-j*hauteur/nl;
    float hf = hi-hauteur/nl;*/
	float hi = hauteur/2;
    float hf = hi-hauteur;
    glBegin(GL_QUAD_STRIP);
    for( int i = 0 ; i <= ns ; i++ ) {
      float a = (2*PI*i)/ns;
      float cs = cos(a);
      float sn = -sin(a);
      glNormal3f(cs,0.0F,sn);
      float x = rayon*cs;
      float z = rayon*sn;
      glVertex3f(x,hi,z);
      glVertex3f(x,hf+0.15*(cos(a*8)+1),z); }
    glEnd(); /*}*/
  if ( bases ) {
    glBegin(GL_POLYGON);
    glNormal3f(0.0F,1.0F,0.0F);
    for( int i = 0 ; i < ns ; i++ ) {
      float a = (2*PI*i)/ns;
      float cs = cos(a);
      float sn = -sin(a);
      float x = rayon*cs;
      float z = rayon*sn;
      glVertex3f(x,hauteur/2.0F,z); }
    glEnd();
    glBegin(GL_POLYGON);
    glNormal3f(0.0F,-1.0F,0.0F);
    for( int i = 0 ; i < ns ; i++ ) {
      float a = (2*PI*i)/ns;
      float cs = cos(a);
      float sn = sin(a);
      float x = rayon*cs;
      float z = rayon*sn;
      glVertex3f(x,-hauteur/2.0F,z); }
    glEnd(); }
  glPopMatrix();
  glNormal3f(normale[0],normale[1],normale[2]);
}
static void solidCube(double ct) {
  float c =(float) ct/2.0F;
  glBegin(GL_QUADS);
  { glNormal3f(0.0F,0.0F,-1.0F);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f( c, c,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f( c,-c,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f(-c,-c,-c);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f(-c, c,-c); }
  { glNormal3f(0.0F,0.0F,1.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f( c, c, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f(-c, c, c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f(-c,-c, c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f( c,-c, c); }
  { glNormal3f(-1.0F,0.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f(-c, c,-c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f(-c,-c,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f(-c,-c, c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f(-c, c, c); }
  { glNormal3f(1.0F,0.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f( c, c, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f( c,-c, c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f( c,-c,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f( c, c,-c); }
  { glNormal3f(0.0F,-1.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f(-c,-c, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f(-c,-c,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f( c,-c,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f( c,-c, c); }
  { glNormal3f(0.0F,1.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f( c, c, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f( c, c,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f(-c, c,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f(-c, c, c); }
  glEnd();
}
static void solidCubeTronque(double ct) {
  float c =(float) ct/2.0F;
  glBegin(GL_QUADS);
  { glNormal3f(0.0F,0.0F,-1.0F);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f( c, c,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f( c,0,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f(-c,0,-c);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f(-c, c,-c); }
  { glNormal3f(0.0F,0.0F,1.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f( c, c, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f(-c, c, c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f(-c,0, c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f( c,0, c); }
  { glNormal3f(-1.0F,0.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f(-c, c,-c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f(-c,0,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f(-c,0, c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f(-c, c, c); }
  { glNormal3f(1.0F,0.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f( c, c, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f( c,0, c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f( c,0,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f( c, c,-c); }
  { glNormal3f(0.0F,-1.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f(-c,0, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f(-c,0,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f( c,0,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f( c,0, c); }
  { glNormal3f(0.0F,1.0F,0.0F);
    glTexCoord2f(0.0F,0.0F);
    glVertex3f( c, c, c);
    glTexCoord2f(1.0F,0.0F);
    glVertex3f( c, c,-c);
    glTexCoord2f(1.0F,1.0F);
    glVertex3f(-c, c,-c);
    glTexCoord2f(0.0F,1.0F);
    glVertex3f(-c, c, c); }
  glEnd();
}

static void drawDemiCylindre(double hauteur,double rayon,int ns,int nl,int bases) {
  
  glEnable(GL_NORMALIZE);
  float normale[4];
  glGetFloatv(GL_CURRENT_NORMAL,normale);
  
  for ( int j = 0 ; j < nl ; j++ ) {
    float hi = hauteur/2-j*hauteur/nl;
    float hf = hi-hauteur/nl;
    glBegin(GL_QUAD_STRIP);
    for( int i = 0 ; i <= ns/2 ; i++ ) {
      float a = (2*PI*i)/ns;
      float cs = cos(a);
      float sn = -sin(a);
      glNormal3f(cs,0.0F,sn);
      float x = rayon*cs;
      float z = rayon*sn;
	  glTexCoord2f((float) i/ns,0.0F);
      glVertex3f(x,hi,z);
	  glTexCoord2f((float) i/ns,1.0F);
      glVertex3f(x,hf,z); }
    glEnd(); }
  if ( bases ) {
    glBegin(GL_POLYGON);
    glNormal3f(0.0F,1.0F,0.0F);
    for( int i = 0 ; i <= ns/2 ; i++ ) {
      float a = (2*PI*i)/ns;
      float cs = cos(a);
      float sn = -sin(a);
      float x = rayon*cs;
      float z = rayon*sn;
	  glTexCoord2f(cs/4.0F,-sn/4.0F);
      glVertex3f(x,hauteur/2.0F,z); }
    glEnd();
    glBegin(GL_POLYGON);
    glNormal3f(0.0F,-1.0F,0.0F);
    for( int i = ns/2 ; i <= ns ; i++ ) {
      float a = (2*PI*i)/ns;
      float cs = cos(a);
      float sn = sin(a);
      float x = rayon*cs;
      float z = rayon*sn;
	  glTexCoord2f(cs/4.0F,sn/4.0F);
      glVertex3f(x,-hauteur/2.0F,z); }
    glEnd(); }

  glNormal3f(normale[0],normale[1],normale[2]);
}

static void drawExtremiteMur(double hauteur,double rayon,int ns,int nl,int bases, Direction direction) {
  glPushMatrix();

  if(direction == NORTH){
	  // nothing
  }else if(direction == SOUTH){
	  glRotatef(180.0F,0.0F,0.0F,1.0F);
  }else if(direction == EAST){
	  glRotatef(90.0F,0.0F,0.0F,1.0F);
  }else if(direction == WEST){
	  glRotatef(-90.0F,0.0F,0.0F,1.0F);
  }

  glPushMatrix();
  glTranslatef(0.0,-0.5,0.0);
  solidCubeTronque(1.0);
  glPopMatrix();

  glRotatef(90.0F,1.0F,0.0F,0.0F);

   drawDemiCylindre(hauteur, rayon, ns, nl, bases);

   glPopMatrix();
}

static void drawFantome(double height, float color[], Direction direction, bool mange){

	float heightEyes = height/2;
	float dEyes = 0.32F;
	float ecartEyes = 0.15F;

	if(!mange){
		glPushMatrix();
		glMaterialfv(GL_FRONT,GL_DIFFUSE,color);
		glTranslatef(0.0F,0.0F,height/2);
		glutSolidSphere(0.5,10,10);
		glTranslatef(0.0F,0.0F,-height/2);
		glRotatef(90.0F,1.0F,0.0F,0.0F);
		mySolidCylindre(height,0.5,50,50,FALSE);
		//cylindre(height,0.5,12,12);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glPopMatrix();
	}

	glPushMatrix();
	if(direction == NORTH){
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(ecartEyes,dEyes,0.0F);

		glTranslatef(0.0F,0.1F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(0.0F,-0.1F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);
		glTranslatef(-2*ecartEyes,0.0F,0.0F);

		glTranslatef(0.0F,0.1F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(0.0F,-0.1F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);

	}else if(direction == SOUTH){
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(ecartEyes,-dEyes,0.0F);

		glTranslatef(0.0F,-0.1F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(0.0F,0.1F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);
		glTranslatef(-2*ecartEyes,0.0F,0.0F);

		glTranslatef(0.0F,-0.1F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(0.0F,0.1F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);
	}else if(direction == EAST){
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(dEyes,ecartEyes,0.0F);

		glTranslatef(0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(-0.1F,0.0F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);
		glTranslatef(0.0F,-2*ecartEyes,0.0F);

		glTranslatef(0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(-0.1F,0.0F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);


	}else if(direction == WEST){
		
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(-dEyes,ecartEyes,0.0F);

		glTranslatef(-0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(0.1F,0.0F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);
		glTranslatef(0.0F,-2*ecartEyes,0.0F);

		glTranslatef(-0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.16,10,10);
		glTranslatef(0.1F,0.0F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.25,10,10);
	}
	glPopMatrix();
}

static void drawFantome2D(double height, float color[], Direction direction, bool mange){
	float heightEyes = height/2;
	float dEyes = 0.32F;
	float ecartEyes = 0.15F;

	if(!mange){
	}
	glPushMatrix();
	glRotatef(90.0,1.0,0.0,0.0);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,color);
	glTranslatef(0.0F,0.0F,height/2);
	glutSolidSphere(0.5,10,10);
	glTranslatef(0.0F,0.0F,-height/2);
	glRotatef(90.0F,1.0F,0.0F,0.0F);
	mySolidCylindre(height,0.5,50,50,FALSE);
	//cylindre(height,0.5,12,12);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
	glPopMatrix();
}

static void drawPacman(Direction direction, int angle, int timer){
	float heightEyes = 0.30F;
	float dEyes = 0.30F;
	float ecartEyes = 0.15F;
	glPushMatrix();
	
	glMaterialfv(GL_FRONT,GL_DIFFUSE,jaune);
	if(timer>0&& timer<100)
		glMaterialfv(GL_FRONT,GL_DIFFUSE,rouge);

	const double eq[] = {0.0,0.0,0.5,0.0};

	if(direction == NORTH){
		glPushMatrix();
		glRotatef(-angle,-1.0,0.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glPushMatrix();
		glRotatef(180+angle,-1.0,0.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glRotatef(-angle,-1.0,0.0,0.0);
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(ecartEyes,dEyes+0.1,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.10,10,10);
		glTranslatef(0.0F,-0.1,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
		glTranslatef(-2*ecartEyes,0.0F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glTranslatef(0.0F,+0.1F,0.0F);	
		glutSolidSphere(0.10,10,10);
		glTranslatef(0.0F,-0.1F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
	}else if(direction == SOUTH){
		glPushMatrix();
		glRotatef(-angle,1.0,0.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glPushMatrix();
		glRotatef(180+angle,1.0,0.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glRotatef(-angle,1.0,0.0,0.0);
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(ecartEyes,-dEyes-0.1,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.10,10,10);
		glTranslatef(0.0F,0.1,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
		glTranslatef(-2*ecartEyes,0.0F,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glTranslatef(0.0F,-0.1F,0.0F);	
		glutSolidSphere(0.10,10,10);
		glTranslatef(0.0F,0.1F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
	}else if(direction == EAST){
		glPushMatrix();
		glRotatef(-angle,0.0,1.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glPushMatrix();
		glRotatef(180+angle,0.0,1.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glRotatef(-angle,0.0,1.0,0.0);
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(dEyes+0.1,ecartEyes,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.10,10,10);
		glTranslatef(-0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
		glTranslatef(0.0F,-2*ecartEyes,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glTranslatef(0.1F,0.0F,0.0F);	
		glutSolidSphere(0.10,10,10);
		glTranslatef(-0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
	}else if(direction == WEST){
		glPushMatrix();
		glRotatef(-angle,0.0,-1.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glPushMatrix();
		glRotatef(180+angle,0.0,-1.0,0.0);
		glClipPlane(GL_CLIP_PLANE0,eq);
		glEnable(GL_CLIP_PLANE0);
		glutSolidSphere(0.5,50,50);
		glDisable(GL_CLIP_PLANE0);
		glPopMatrix();

		glRotatef(-angle,0.0,-1.0,0.0);
		glTranslatef(0.0F,0.0F,heightEyes);
		glTranslatef(-dEyes-0.1,ecartEyes,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glutSolidSphere(0.10,10,10);
		glTranslatef(+0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
		glTranslatef(0.0F,-2*ecartEyes,0.0F);

		glMaterialfv(GL_FRONT,GL_DIFFUSE,noir);
		glTranslatef(-0.1F,0.0F,0.0F);	
		glutSolidSphere(0.10,10,10);
		glTranslatef(+0.1F,0.0F,0.0F);
		glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
		glutSolidSphere(0.15,10,10);
	}
	glPopMatrix();
}

static void drawPacman2D(Direction direction, int angle, int timer){
	float heightEyes = 0.30F;
	float dEyes = 0.30F;
	float ecartEyes = 0.15F;
	glPushMatrix();
	
	glMaterialfv(GL_FRONT,GL_DIFFUSE,jaune);
	if(timer>0&& timer<100)
		glMaterialfv(GL_FRONT,GL_DIFFUSE,rouge);

	//glutSolidSphere(0.5,20,20);
	glRotatef(90.0, 1.0,0.0,0.0);

	if(direction == NORTH){
		glPushMatrix();
		glRotatef(-angle-90, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
		glPopMatrix();
		glRotatef(90+angle, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
	}else if(direction == SOUTH){
		glPushMatrix();
		glRotatef(-angle+90, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
		glPopMatrix();
		glRotatef(angle-90, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
	}else if(direction == EAST){
		glPushMatrix();
		glRotatef(180-angle, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
		glPopMatrix();
		glRotatef(angle, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
	}else if(direction == WEST){
		glPushMatrix();
		glRotatef(-angle, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
		glPopMatrix();
		glRotatef(180+angle, 0.0,1.0,0.0);
		drawDemiCylindre(0.5, 0.5, 20, 1, true);
	}
	glPopMatrix();
}
/*
void drawBordMurT(){
	glBegin(GL_POLYGON);
	//glNormal3f(-1.0,0.0,0.0);
	glVertex3f(0.5,-0.5,0.5);
	glVertex3f(0.5,-0.5,-0.5);
	glVertex3f(0.5,0.5,-0.5);
	glVertex3f(0.5,0.5,0.5);
	glEnd();
	glBegin(GL_POLYGON);
	//glNormal3f(0.0,-1.0,0.0);
	glVertex3f(0.5,0.5,-0.5);
	glVertex3f(0.5,0.5,0.5);
	glVertex3f(-0.5,0.5,0.5);
	glVertex3f(-0.5,0.5,-0.5);
	glEnd();
	glBegin(GL_POLYGON);
	//glNormal3f(-1.0,-1.0,0.0);
	glVertex3f(-0.5,0.5,0.5);
	glVertex3f(-0.5,0.5,-0.5);
	glVertex3f(0.5,-0.5,-0.5);
	glVertex3f(0.5,-0.5,0.5);
	glEnd();
	glBegin(GL_POLYGON);
	//glNormal3f(0.0,0.0,1.0);
	glVertex3f(0.5,-0.5,0.5);
	glVertex3f(0.5,0.5,0.5);
	glVertex3f(-0.5,0.5,0.5);
	glEnd();
	glBegin(GL_POLYGON);
	//glNormal3f(0.0,0.0,-1.0);
	glVertex3f(-0.5,0.5,-0.5);
	glVertex3f(0.5,0.5,-0.5);
	glVertex3f(0.5,-0.5,-0.5);
	glEnd();
}
*/
void drawMur(int x, int y, Grille *grille, float size){
	glPushMatrix();

	glScalef(1.0,1.0,0.5);
	glTranslatef(0.0,0.0,-0.5);
	if(grille->isFill(x-1,y) && grille->isFill(x+1,y)){
		solidCube(size);
	}else if(grille->isFill(x,y-1) && grille->isFill(x,y+1)){
		solidCube(size);
	}else{
		if(grille->isFill(x-1,y) && grille->isFill(x,y-1)){
			solidCube(size);
		}else if(grille->isFill(x-1,y) && grille->isFill(x,y+1)){
			solidCube(size);
		}else if(grille->isFill(x+1,y) && grille->isFill(x,y-1)){
			solidCube(size);
		}else if(grille->isFill(x+1,y) && grille->isFill(x,y+1)){
			solidCube(size);
		}else{
			if(grille->isFill(x,y+1)){
				drawExtremiteMur(1.0F,size/2,10,1,TRUE,NORTH);
			}else if(grille->isFill(x,y-1)){
				drawExtremiteMur(1.0F,size/2,10,1,TRUE,SOUTH);
			}else if(grille->isFill(x+1,y)){
				drawExtremiteMur(1.0F,size/2,10,1,TRUE,EAST);
			}else if(grille->isFill(x-1,y)){
				drawExtremiteMur(1.0F,size/2,10,1,TRUE,WEST);
			}else{
				glutSolidSphere(0.5,25,25);
			}
		}
	}

	glPopMatrix();
}
void dessineMenu(void){

	glPushMatrix();
	glTranslatef(0.0,20.0,20.0);
	glRotatef(-45.0,1.0,0.0,0.0);

	glEnable(GL_BLEND);
	glBegin(GL_POLYGON);
	float bleu[4] = {0.0,0.0,1.0,0.5};
	glMaterialfv(GL_FRONT,GL_DIFFUSE,bleu);
	glNormal3f(0.0,0.0,10.0);
	glTexCoord2f(10.0F,10.0F);
	glVertex2f(-1,-1);
	glTexCoord2f(0.0F,10.0F);
    glVertex2f(1,-1);
	glTexCoord2f(0.0F,0.0F);
	glVertex2f(1,1);
	glTexCoord2f(10.0F,0.0F);
	glVertex2f(-1,1);
	glEnd();
	glDisable(GL_BLEND);
	glPopMatrix();
}

string convertInt(int number)
{
	stringstream ss;
	ss << number;
	return ss.str();
}

void dessineScore(void){
	glPushMatrix();
	glTranslatef(0.0,20.0,20.0);
	//glTranslatef(0.0,-1.0,1.0);
	glRotatef(-45.0,1.0,0.0,0.0);

	glEnable(GL_BLEND);
	glBegin(GL_POLYGON);
	float bleu[4] = {0.0,0.0,1.0,0.5};
	glMaterialfv(GL_FRONT,GL_DIFFUSE,bleu);
	glNormal3f(0.0,0.0,1.0);
	glVertex2f(-1,-1);
    glVertex2f(1,-1);
	glVertex2f(1,1);
	glVertex2f(-1,1);
	glEnd();
	glDisable(GL_BLEND);
	glPopMatrix();

	Joueur joueur = game.getJoueur();
	string score("Mon score ");
	score.append(convertInt(joueur.score));
	char *tmp = (char *) malloc(score.length()*sizeof(char));
	strcpy(tmp, score.c_str());
	glPushMatrix();
	glTranslatef(0.0,10.0,10.0);
	glutPrint(5,-5, GLUT_BITMAP_HELVETICA_18, tmp, 0.0, 0.0,0.0,1.0);
	glPopMatrix();
	//delete(tmp);
}


enum VUE{
	VUE_3D,
	VUE_2D
};

void dessinerPlateau(bool texture, VUE vue){
	
	if(texture){
		glEnable(GL_TEXTURE_2D);

		unsigned char *img = loadRawImage("Damier2.raw");
		glPixelStorei(GL_UNPACK_ALIGNMENT,1); 
		glTexImage2D(GL_TEXTURE_2D,0,3,64,64,0,GL_RGB,GL_UNSIGNED_BYTE,img);
		glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); 
		glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
		glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
		glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
		free(img);
	}

	glPushMatrix();
	
	Grille* grille = game.getGrille();
	
	glTranslatef((float)-grille->getWidth()/2,(float)-grille->getHeight()/2,0.0);
	
	for(int y=grille->getHeight()-1; y>=0; y--){
		glPushMatrix();
		for(int x=0; x<grille->getWidth(); x++){
			if(grille->isFill(x,y)){
				glMaterialfv(GL_FRONT,GL_DIFFUSE,bleu);
				drawMur(x,y,grille,1.0);
				//glutSolidCube(1.0);
				glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
			}else if(grille->get(x,y)==2){
				glMaterialfv(GL_FRONT,GL_DIFFUSE,jaune);
				glutSolidSphere(0.25,25,25);
				glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
			}else if(grille->get(x,y)==3){
				//glutSolidSphere(0.5,50,50);
			}else if(grille->get(x,y)==0){
				glMaterialfv(GL_FRONT,GL_DIFFUSE,jaune);
				glutSolidSphere(0.15,10,10);
				glMaterialfv(GL_FRONT,GL_DIFFUSE,blanc);
			}
			glTranslatef(1.0,0.0,0.0);
		}
		glPopMatrix();
		glTranslatef(0.0,1.0,0.0);
	}
	
	glPopMatrix();

	if(texture){
		glDisable(GL_TEXTURE_2D);
	}

	
	glPushMatrix();
	Joueur joueur = game.getJoueur();
	glTranslatef(joueur.pos.x-grille->getWidth()/2-0.5,grille->getHeight()/2-joueur.pos.y-0.5,0.0);
	
	compteur++;

	int timer = -1;
	if(joueur.mode == MODEJ_SUPERPACMAN){
		glTranslatef(0.0,0.0,0.5);
		glScalef(1.25,1.25,1.25);
		timer = joueur.timer;
	}
	if(vue == VUE_3D){
		drawPacman(joueur.direction,(sin(compteur/PI/4)+1)/2*60,timer);
	}else{
		drawPacman2D(joueur.direction,(sin(compteur/PI/4)+1)/2*60,timer);
	}
	glPopMatrix();

	
	for(int i=0; i<game.getNbFantome(); i++){
		Fantome fantome = game.getFantome(i);
		glPushMatrix();
		glTranslatef(fantome.pos.x-grille->getWidth()/2-0.5,grille->getHeight()/2-fantome.pos.y-0.5,0.0);

		if(joueur.mode == MODEJ_SUPERPACMAN){
			glScalef(0.75,0.75,0.75);
		}
		bool mange = fantome.mode == MODEF_MANGE;
		if(vue == VUE_3D){
			drawFantome(0.8,fantome.couleur,fantome.direction,mange);
		}else{
			drawFantome2D(0.8,fantome.couleur,fantome.direction,mange);
		}
		glPopMatrix();
	}
	
	
}

static void init(void) {
  const GLfloat shininess[] = { 50.0 };
  glMaterialfv(GL_FRONT,GL_SPECULAR,blanc);
  glMaterialfv(GL_FRONT,GL_SHININESS,shininess);
  glLightfv(GL_LIGHT0,GL_DIFFUSE,blanc);
  glLightfv(GL_LIGHT1,GL_DIFFUSE,blanc);
  glLightfv(GL_LIGHT2,GL_DIFFUSE,blanc);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHT1);
  glEnable(GL_LIGHT2);
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  glEnable(GL_AUTO_NORMAL);
  
  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

  glLightf(GL_LIGHT2,GL_CONSTANT_ATTENUATION,0.3F);
  glLightf(GL_LIGHT2,GL_LINEAR_ATTENUATION,0.0F);
  glLightf(GL_LIGHT2,GL_QUADRATIC_ATTENUATION,0.005F);
}

static void idle(void) {
  
  glutPostWindowRedisplay(vueDessus);
  glutPostWindowRedisplay(vueInterne);
  glutPostWindowRedisplay(vueOrtho);

  //usleep(1000);
  Sleep(50);
}


static void scene(void) {
	Joueur joueur = game.getJoueur();
	Grille* grille = game.getGrille();

	//dessineScore();

	glPushMatrix();

	float posX = (float)grille->getWidth()/2.0-joueur.pos.x;
	float posY = (float)-grille->getHeight()/2.0+joueur.pos.y;
	glTranslatef(posX,posY,0.0);

	// tilt : Game Over ...
	static int timer=0;
	
	if(game.getLose()){
		if(timer<30){
			glTranslatef(-cos(compteur/PI*8)*0.1,-sin(compteur/PI*8)*0.1,0.0);
			timer++;
		}else{
			timer=0;
			anim = !anim;
			game.refresh();
			glutIdleFunc(( anim ) ? idle : NULL);
		}
	}

	dessinerPlateau(false,VUE_3D);

	glPopMatrix();
}


static void display(void) {
  game.play();
  
  glClearColor(0.1F,0.1F,0.1F,1.0F);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  const GLfloat light0_position[] = { 5.0,10.0,15.0,1.0 };
  const GLfloat light1_position[] = { 0.0,-10.0,10.0,0.0 };
  const GLfloat light2_position[] = { 0.0, 35.0,35.0,1.0 };
  const GLfloat light2_direction[] = { 0.0,-1.0,-1.0, 0.0 };

  glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
  glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
  glLightfv(GL_LIGHT2,GL_POSITION,light2_position);
  glLightfv(GL_LIGHT2,GL_SPOT_DIRECTION,light2_direction);
  glLightf(GL_LIGHT2,GL_SPOT_CUTOFF,5.0);
  glMaterialfv(GL_BACK,GL_DIFFUSE,rouge);
  //glColor3f(1.0,1.0,1.0);

  scene();

  if(!game.isBegin()){
	dessineMenu();
  }

  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Attention erreur %d\n",error);
}

static void scene2(void) {
	Joueur joueur = game.getJoueur();
	Grille* grille = game.getGrille();

	glPushMatrix();

	float posX = (float)grille->getWidth()/2-joueur.pos.x;
	float posY = (float)-grille->getHeight()/2+joueur.pos.y;

	glTranslatef(posX, posY, 0.0);
	
		// tilt : Game Over ...
	static int timer=0;
	
	if(game.getLose()){
			glTranslatef(-cos(compteur/PI*8)*0.1,-sin(compteur/PI*8)*0.1,0.0);
	}

	dessinerPlateau(true, VUE_3D);

	glPopMatrix();
}

static void display2(void) {
  game.play();
  
  glClearColor(0.1F,0.1F,0.1F,1.0F);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  const GLfloat light0_position[] = { 5.0,10.0,15.0,1.0 };
  const GLfloat light1_position[] = { 0.0,-10.0,10.0,0.0 };
  const GLfloat light2_position[] = { 0.0, 35.0,35.0,1.0 };
  const GLfloat light2_direction[] = { 0.0,-1.0,-1.0, 0.0 };

  glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
  glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
  glLightfv(GL_LIGHT2,GL_POSITION,light2_position);
  glLightfv(GL_LIGHT2,GL_SPOT_DIRECTION,light2_direction);
  glLightf(GL_LIGHT2,GL_SPOT_CUTOFF,5.0);
  glMaterialfv(GL_BACK,GL_DIFFUSE,rouge);

  scene2();

  if(!game.isBegin()){
	dessineMenu();
  }

  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Attention erreur %d\n",error);
}

void sceneOrtho(){
	dessinerPlateau(false,VUE_2D);
}

static void displayOrtho(void) {
  game.play();
  
  glClearColor(0.1F,0.1F,0.1F,1.0F);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  const GLfloat light0_position[] = { 5.0,10.0,15.0,1.0 };
  const GLfloat light1_position[] = { 0.0,-10.0,10.0,0.0 };
  const GLfloat light2_position[] = { 0.0, 35.0,35.0,1.0 };
  const GLfloat light2_direction[] = { 0.0,-1.0,-1.0, 0.0 };

  glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
  glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
  glLightfv(GL_LIGHT2,GL_POSITION,light2_position);
  glLightfv(GL_LIGHT2,GL_SPOT_DIRECTION,light2_direction);
  glLightf(GL_LIGHT2,GL_SPOT_CUTOFF,5.0);
  glMaterialfv(GL_BACK,GL_DIFFUSE,rouge);

  sceneOrtho();

  if(!game.isBegin()){
	dessineMenu();
  }

  glFlush();
  glutSwapBuffers();
  int error = glGetError();
  if ( error != GL_NO_ERROR )
    printf("Attention erreur %d\n",error);
}

static void reshape(int x,int y) {
  glViewport(0,0,x,y); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(20.0F,(float) x/y,1.0,60.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  gluLookAt(0.0,30.0,30.0,0.0,0,0.0,0.0,0.0,1.0);
}

static void reshape2(int x,int y) {
  glViewport(0,0,x,y); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(20.0F,(float) x/y,1.0,60.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  
  Joueur joueur = game.getJoueur();
  
  gluLookAt(0.0,3.0,4.0,
	  0.0,-1.0,0.0,
	  0.0,0.0,1.0);
}

static void reshapeOrtho(int x,int y) {
  glViewport(0,0,x,y); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  
  float tailleX = game.getGrille()->getWidth()/2+1;
  float tailleY = game.getGrille()->getHeight()/2+1;

  if ( x >= y )
    glOrtho(-tailleX*(float) x/y,tailleX*(float) x/y,-tailleY,tailleY,-10.0,10.0);
  else
    glOrtho(-tailleX,tailleX,-tailleY*(float) y/x,tailleY*(float) y/x,-10.0,10.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  gluLookAt(0.0,0.0,4.0,
	  0.0,-1.0,0.0,
	  0.0,0.0,1.0);
}

static void keyboard(unsigned char key,int x,int y) {
  switch (key) {
    case 0x0D :
      { 
        anim = !anim;
        glutIdleFunc(( anim ) ? idle : NULL); }
      break;
    case 0x1B :
      exit(0);
      break; 
    case 0x34 : { // Left
	  game.setDirectionJoueur(EAST);
      break;
	}
    case 0x36 : { // Right
	  game.setDirectionJoueur(WEST);
      break;
	}
    case 0x38 : { // Top
	  game.setDirectionJoueur(SOUTH);
      break;
	}
    case 0x32 : {// Down
	  game.setDirectionJoueur(NORTH);
      break;
	}
    default:
      break;
  }
}


static void mouse(int bouton,int etat,int x,int y) {
  if (bouton == GLUT_LEFT_BUTTON){
	  if(!game.isBegin()){
		anim = 1;
		glutIdleFunc(( anim ) ? idle : NULL);
		game.start();
	  }
  }
  if (bouton == GLUT_RIGHT_BUTTON){}
}

int main(int argc,char **argv){

  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  glutInitWindowSize(640,480);
  glutInitWindowPosition(50,50);
  vueDessus = glutCreateWindow("Pacman !!!");
  init();
  glutKeyboardFunc(keyboard);
  glutMouseFunc(mouse);
  glutReshapeFunc(reshape);
  glutDisplayFunc(display);
  
  vueInterne = glutCreateWindow("Pacman !!!");
  init();
  glutKeyboardFunc(keyboard);
  glutMouseFunc(mouse);
  glutReshapeFunc(reshape2);
  glutDisplayFunc(display2);
  
  vueOrtho = glutCreateWindow("Pacman !!!");
  init();
  glutKeyboardFunc(keyboard);
  glutMouseFunc(mouse);
  glutReshapeFunc(reshapeOrtho);
  glutDisplayFunc(displayOrtho);
  
  glutIdleFunc(idle);
  
  glutMainLoop();


}
